package com.zhixing.web.common.utils;

import lombok.extern.slf4j.Slf4j;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * @author dzh
 * @version 1.0.0.05020
 * <p>project: d-blog</p>
 * <p>created time: 2022/05/02 15:17</p>
 * <p>describe: 时间操作工具类。</p>
 * <p>remarks: </p>
 **/
@Slf4j
public class DateUtil {

    /**
     * Base ISO 8601 Date format yyyyMMdd i.e., 20021225 for the 25th day of December in the year 2002
     */
    public static final String ISO_DATE_FORMAT = "yyyyMMdd";

    /**
     * Expanded ISO 8601 Date format yyyy-MM-dd i.e., 2002-12-25 for the 25th day of December in the year 2002
     */
    public static final String ISO_EXPANDED_DATE_FORMAT = "yyyy-MM-dd";

    /**
     * yyyy-MM-dd hh:mm:ss
     */
    public static final String DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

    /**
     * yyyy-MM-dd hh:mm:ss
     */
    public static final String DATETIME_MILLISECOND_PATTERN = "yyyy-MM-dd HH:mm:ss.SSS";

    /**
     * yyyyMMddHHmmss
     */
    public static final String DATE_PATTERN = "yyyyMMddHHmmss";

    /**
     * 空字符
     * */
    private static final String NULL_CHAR = "null";

    /**
     * @author lkt
     * @return String : 当前时间 yyyy-MM-dd HH:mm:ss.SSS
     * <p>时间：2021-01-12 13:00</p>
     * <p>描述：当前时间 年-月-日 时:分:秒.毫秒</p>
     **/
    public static String getCurrentTimeMilliSecond() {

        SimpleDateFormat df = new SimpleDateFormat(DATETIME_MILLISECOND_PATTERN);

        return df.format(new Date());
    }

    /**
     * @author lkt
     * @return String : 当前时间 年-月-日 时:分:秒
     * <p>时间：2021-01-12 13:00</p>
     * <p>描述：当前时间 年-月-日 时:分:秒</p>
     **/
    public static String getCurrentTime() {

        SimpleDateFormat df = new SimpleDateFormat(DATETIME_PATTERN);

        return df.format(new Date());
    }

    /**
     * @author lkt
     * @return String : 当前时间 无符号类型
     * <p>时间：2021-01-12 13:00</p>
     * <p>描述：当前时间 年月日时分秒</p>
     **/
    public static String getCurrentTimeUnformat() {

        SimpleDateFormat df = new SimpleDateFormat(DATE_PATTERN);

        return df.format(new Date());
    }

    /**
     * 当前时间 时:分:秒
     * */
    public static String getMinutesAndSeconds() {

        SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");

        return df.format(new Date());
    }

    /**
     * 当前日期 年-月-日
     * */
    public static String getCurrentDate() {

        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");

        return df.format(new Date());
    }

    /**
     * 当前年
     * */
    public static String getCurrentYear() {

        SimpleDateFormat df = new SimpleDateFormat("yyyy");

        return df.format(new Date());
    }

    /**
     * 当前月
     * */
    public static String getCurrentMonth() {

        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM");

        return df.format(new Date());
    }

    /**
     * @param format "yyyy-MM-dd" / "yyyy-MM-dd HH:mm:ss"
     * @param span 1000 秒 1000 * 60 分钟 1000*3600*24 天
     * 计算时间差
     * */
    public static String calcTimeDifference(String startTime, String endTime, String format, int span) {

        DateFormat df = new SimpleDateFormat(format);

        try {
            Date d1 = df.parse(startTime);
            Date d2 = df.parse(endTime);
            long diff = d1.getTime() - d2.getTime();

            return String.valueOf(diff/span);
        } catch (Exception e)  {

            log.error("[计算时间差出现异常] ## {} ## {} ## {}",
                    getCurrentTimeMilliSecond(),
                    "DateUtil.calcTimeDifference",
                    startTime + ", " + endTime + ", " + format + ", " + span);
            return "0";
        }
    }

    /**
     * 时间戳转日期时间
     * */
    public static String timeStamp2Date(String seconds, String format) {

        if(seconds == null || seconds.isEmpty() || NULL_CHAR.equals(seconds)){

            return "";
        }

        if(format == null || format.isEmpty()){

            format = "yyyy-MM-dd HH:mm:ss";
        }

        SimpleDateFormat sdf = new SimpleDateFormat(format);

        return sdf.format(new Date(Long.valueOf(seconds)));
    }

    /**
     * 时间转时间戳
     * suffixValue 仅需要时间戳时 为 1 即可
     * 需要扩大位数时 可设置为100 1000 10000等
     * */
    public static String date2TimeStamp(String dateStr, String format, int suffixValue) {

        try {

            SimpleDateFormat sdf = new SimpleDateFormat(format);

            return String.valueOf(sdf.parse(dateStr).getTime() * suffixValue);

        } catch (Exception e) {

            e.printStackTrace();
        }
        return "";
    }

    /**
     * @param time 指定的时间
     * @param n 时间数
     * 描述 获取当前时间，任意天数之前或之后的时间
     * @param mode D Calendar.DAY_OF_MONTH H Calendar.HOUR_OF_DAY M Calendar.MINUTE S Calendar.SECOND
     **/
    public static String getBeforeOrAfterDateTime(String time, Integer n, boolean needHms, String mode) {

        SimpleDateFormat sdf;

        if (needHms) {

            sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        } else {

            sdf = new SimpleDateFormat("yyyy-MM-dd");
        }

        Date date = new Date();

        try {

            date = sdf.parse(time);
        } catch (ParseException e) {

            log.error("[获取当前时间下之前或之后时间异常] ## {} ## {} ## {}",
                    getCurrentTimeMilliSecond(),
                    "DateUtil.getBeforeOrAfterDateTime",
                    time + ", " + n + ", " + needHms + ", " + mode);
        }

        Calendar calendar = Calendar.getInstance();

        calendar.setTime(date);

        switch(mode) {

            case "D" :
                calendar.add(Calendar.DAY_OF_MONTH, n);
                break;
            case "H" :
                calendar.add(Calendar.HOUR_OF_DAY, n);
                break;
            case "M" :
                calendar.add(Calendar.MINUTE, n);
                break;
            case "S" :
                calendar.add(Calendar.SECOND, n);
                break;
            default :
                calendar.add(Calendar.DAY_OF_MONTH, n);
                break;
        }

        date = calendar.getTime();

        return sdf.format(date);
    }

    /**
     * 描述 获取当前月的第一天
     **/
    public static String getMonthFirstDay() {

        DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH, 1);

        return sdf.format(calendar.getTime());
    }

    /**
     * 描述 获取当前月的最后一天
     **/
    public static String getMonthLastDay() {

        DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));

        return sdf.format(calendar.getTime());
    }

    /**
     * 描述 获取指定月的第一天
     **/
    public static String getAppointMonthFirstDay(String time) {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");

        Date date = new Date();

        try {

            date = sdf.parse(time);
        } catch (ParseException e) {

            log.error("[获取指定月的第一天] ## {} ## {} ## {}",
                    getCurrentTimeMilliSecond(),
                    "DateUtil.getAppointMonthFirstDay",
                    time);
        }

        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, 1);

        return df.format(calendar.getTime());
    }

    /**
     * 描述 获取指定月的最后一天
     **/
    public static String getAppointMonthLastDay(String time) {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");

        Date date = new Date();

        try {

            date = sdf.parse(time);
        } catch (ParseException e) {

            log.error("[获取指定月的最后一天] ## {} ## {} ## {}",
                    getCurrentTimeMilliSecond(),
                    "DateUtil.getAppointMonthFirstDay",
                    time);
        }

        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));

        return df.format(calendar.getTime());
    }

    /**
     * 描述 比较时间大小 第一个时间大于第二个时间 返回 true 反之 false
     * @param firstTime 第一个时间
     * @param secondTime 第二个时间
     * @param type 比较类型 "HH:mm:ss" "yyyy-MM-dd" "yyyy-MM-dd HH:mm:ss"
     * @return boolean
     **/
    public static boolean compareToTime(String firstTime, String secondTime, String type) {

        SimpleDateFormat sdf = new SimpleDateFormat(type);

        try {

            Date dt1 = sdf.parse(firstTime);

            Date dt2 = sdf.parse(secondTime);

            return dt1.getTime() > dt2.getTime();
        } catch (ParseException e) {

            e.printStackTrace();
        }

        return false;
    }

    /**
     * 描述 获取传入时间的相关信息
     * @param time 时间 yyyy-MM-dd HH:mm:ss等
     * @param typeResult 转换后结果 "HH:mm:ss" "yyyy-MM-dd" "yyyy" "MM" "dd" "HH" "mm" "ss" "yyyy-MM-dd HH:mm:ss"等
     * @param typeTran 需要转换的格式 "yyyyMMddHHmmss"
     **/
    public static String getTimeMsg(String time, String typeTran, String typeResult) {

        try {

            DateFormat timeFormat = new SimpleDateFormat(typeTran);

            Date date = timeFormat.parse(time);

            SimpleDateFormat sdf = new SimpleDateFormat(typeResult);

            return sdf.format(date);

        } catch (Exception e) {

            return time;
        }
    }

    /**
     * 描述 获取 距离凌晨 新一天的时间差 例如 当前时间2020-01-05 18:34:56 距离 2020-01-06 00:00:00 还有 19504秒
     * */
    public static Integer getTimeDifference() {

        Date currentDate = new Date();

        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");

        DateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        Calendar calendar = Calendar.getInstance();

        try {

            calendar.setTime(timeFormat.parse(df.format(currentDate) + " 00:03:00"));
        } catch (ParseException e) {

            e.printStackTrace();
        }

        calendar.add(Calendar.DAY_OF_MONTH, 1);

        Date nextDate = calendar.getTime();

        long diff = (nextDate.getTime() - currentDate.getTime())/1000;

        return (int)diff;
    }

    /**
     * 当前星期
     * */
    public static Integer getCurrentWeek() {

        Calendar calendar = Calendar.getInstance();

        Integer week = calendar.get(Calendar.DAY_OF_WEEK) - 1;

        if (week == 0) {

            week = 7;
        }

        return week;
    }
}
